package com.lz.autotest.project.testmanage.autoTest.service.Engine;

import com.lz.autotest.project.testmanage.autoTest.service.thread.ThreadContext;
import com.lz.autotest.project.testmanage.autoTest.service.thread.ThreadGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author: X
 * @date: Created in 2023/6/25 15:30
 * @Description: 测试对象
 */
public class StandardXtsEngine implements XtsEngine , Runnable {

    private static final Logger logger = LoggerFactory.getLogger(StandardXtsEngine.class);

    private static final AtomicInteger THREAD_COUNTER = new AtomicInteger(0);

    private int groupCount;

    private ThreadContext threadContext;

    private volatile Future<?> runningTest;

    private volatile boolean running = false;

    private final List<ThreadGroup> groups = new CopyOnWriteArrayList<>();

    private static final ExecutorService EXECUTOR_SERVICE =
            new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                    1L, TimeUnit.SECONDS,
                    new java.util.concurrent.SynchronousQueue<>(),
                    (runnable) -> new Thread(runnable, "StandardXtsEngine-" + THREAD_COUNTER.incrementAndGet()));


    @Override
    public void configure(Integer groupNum, ThreadContext threadContext) {
        this.groupCount = groupNum;
        this.threadContext = threadContext;
    }

    @Override
    public void runTest() {
        try {
            runningTest = EXECUTOR_SERVICE.submit(this);
        } catch (Exception err) {
            stopTest();
        }
    }

    @Override
    public void stopTest(boolean now) {
        EXECUTOR_SERVICE.submit(new StopTest(now));
    }

    private class StopTest implements Runnable {

        private final boolean now;

        private StopTest(boolean b) {
            now = b;
        }

        /**
         *  关闭线程组
         */
        private void tellThreadGroupsToStop() {

            for (ThreadGroup threadGroup : groups) {
                threadGroup.tellThreadsToStop();
            }
        }

        /**
         *  校验线程组是否关闭
         */
        private boolean verifyThreadsStopped() {

            for (ThreadGroup threadGroup : groups) {
                if(!threadGroup.verifyThreadsStopped()) {
                    return false;
                }
            }
            return true;
        }

        @Override
        public void run() {
            running = false;
            if (now) {
                tellThreadGroupsToStop();

                boolean stopped = verifyThreadsStopped();
                if (!stopped) {  // we totally failed to stop the data
//                    logger.error("停止失败");
                } // else will be done by threadFinished()
            }
        }
    }


    @Override
    public void run() {
        ThreadGroup threadGroup = new ThreadGroup();
        startThreadGroup(threadGroup, groupCount);
    }

    private void startThreadGroup(ThreadGroup group, int groupCount)
    {
        groups.add(group);
        group.start(groupCount, threadContext);
    }

}
